# 编写一个程序，找到两个单链表相交的起始节点。 
# 
#  如下面的两个链表： 
# 
#  
# 
#  在节点 c1 开始相交。 
# 
#  
# 
#  示例 1： 
# 
#  
# 
#  输入：intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, s
# kipB = 3
# 输出：Reference of the node with value = 8
# 输入解释：相交节点的值为 8 （注意，如果两个链表相交则不能为 0）。从各自的表头开始算起，链表 A 为 [4,1,8,4,5]，链表 B 为 [5,0,1
# ,8,4,5]。在 A 中，相交节点前有 2 个节点；在 B 中，相交节点前有 3 个节点。
#  
# 
#  
# 
#  示例 2： 
# 
#  
# 
#  输入：intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB =
#  1
# 输出：Reference of the node with value = 2
# 输入解释：相交节点的值为 2 （注意，如果两个链表相交则不能为 0）。从各自的表头开始算起，链表 A 为 [0,9,1,2,4]，链表 B 为 [3,2,4
# ]。在 A 中，相交节点前有 3 个节点；在 B 中，相交节点前有 1 个节点。
#  
# 
#  
# 
#  示例 3： 
# 
#  
# 
#  输入：intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
# 输出：null
# 输入解释：从各自的表头开始算起，链表 A 为 [2,6,4]，链表 B 为 [1,5]。由于这两个链表不相交，所以 intersectVal 必须为 0，而
#  skipA 和 skipB 可以是任意值。
# 解释：这两个链表不相交，因此返回 null。
#  
# 
#  
# 
#  注意： 
# 
#  
#  如果两个链表没有交点，返回 null. 
#  在返回结果后，两个链表仍须保持原有的结构。 
#  可假定整个链表结构中没有循环。 
#  程序尽量满足 O(n) 时间复杂度，且仅用 O(1) 内存。 
#  
#  Related Topics 链表 
#  👍 1110 👎 0


from typing import List


class ListNode:
    def __init__(self, x, next=None):
        self.val = x
        self.next = next


# leetcode submit region begin(Prohibit modification and deletion)
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        if headA is None or headB is None:
            return None
        h1 = headA
        h2 = headB
        while h1 != h2:
            h1 = h1.next if h1 is not None else headB
            h2 = h2.next if h2 is not None else headA
        return h1


# leetcode submit region end(Prohibit modification and deletion)


def log(*args, **kwargs):
    print(*args, **kwargs)


"""
相交链表, 即相交节点之后的所有节点都相同(重合)
"""
# 1. 双层for循环(m * n), 判断有无相同的节点
# def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
#     if headA is None or headB is None:
#         return None
#     while headA is not None:
#       # 临时值, 保证一次循环后, b从头开始循环
#         temp_b = headB
#         while temp_b is not None:
#             if headA == temp_b:
#                 return headA
#             temp_b = temp_b.next
#         headA = headA.next
#     return None
# 2. set存节点, 判断是否在set中, 两次for循环(m + n)
# def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
#     a_set = set()
#     while headA is not None:
#         a_set.add(headA)
#         headA = headA.next
#     while headB is not None:
#         if headB in a_set:
#             return headB
#         headB = headB.next
#     return None
# 拼接链表 a : [0,9,1,2,4], b: [3,2,4]
# 拼接之后, 两个链表走的路一样长, 如果不相交, 则会同时走到断头路
# 图形: 相交: y, 不相交 ||
# 1: [0,9,1,2,4,3,2,4]
# 2: [3,2,4,0,9.1,2,4]
# a: 1 b:2
# 1,2 3
# 3,1,2
# def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
#     if headA is None or headB is None:
#         return None
#     h1 = headA
#     h2 = headB
#     while h1 != h2:
#         h1 = h1.next if h1 is not None else headB
#         h2 = h2.next if h2 is not None else headA
#     # 都不相同 则都为none, 退出
#     return h1

if __name__ == '__main__':
    s = Solution()
    # headA: [0,9,1,2,4], headB: [3,2,4]
    i_node = ListNode(2, ListNode(4))
    head_a = ListNode(0, ListNode(9, ListNode(1, i_node)))
    head_b = ListNode(3, i_node)
    result = s.getIntersectionNode(head_a, head_b)
    assert result == i_node, result
    h_1 = ListNode(1)
    h_2 = ListNode(2)
    result2 = s.getIntersectionNode(h_1, h_2)
    assert result2 is None
